import Utils from '../utils/index';
import Dom from '../utils/Dom';
import Events from '../utils/Events';
import Dimmer from './Dimmer';
import config from '../config';

class ContextMenu {
    /**
     * 右键菜单组件
     * @param {Array} items 菜单项目
     * @param {DOM Event} event 点击事件对象
     * @param {object} options 配置
     */
    constructor(items, callback, event, options) {
        this.items = items;
        this.callback = callback;
        this.event = event;
        this.userOptions = Utils.extend({

        }, options);

        this.root = Dom.append(document.body, 'div', 'contextmenu');

        this.dimmer = new Dimmer(() => {
            this.show(null, true);
        }, {
                opacity: 0
            });

        this.init();
    }

    init() {
        this.items.forEach((item, index) => {
            this.addItem(item, index);
        });

        Dom.addEvent(this.root, 'click', e => {

            var target = e.target;
            if (target.tagName === 'SPAN') {
                target = target.parentNode;
            }

            if (target.className.indexOf('ctx-item') !== -1) {
                if (this.callback(target.dataIndex)) {
                    this.show(null, true);
                }
            }
            return Dom.nodefault(e);
        });

        let subMousemoveTimer = null;
        Dom.addEvent(this.root, 'mousemove', e => {
            let target = e.target;

            if (subMousemoveTimer) {
                clearTimeout(subMousemoveTimer);
            }

            subMousemoveTimer = setTimeout(() => {
                if (target.tagName === 'SPAN') {
                    target = target.parentNode;
                }

                if (target.getAttribute('data-index')) {
                    return Dom.nodefault(e);
                }

                if (target.className.indexOf('ctx-sub') !== -1) {
                    this.showSub(target.dataIndex);
                } else {
                    this.hideSub()
                }
                subMousemoveTimer = null;
            }, 300);
        });

        Events.on(config.eventKey.windowResize, () => {
            this.show(null, true);
        });
        this.show();
    }

    /**
     * @api
     * @param {*} item 
     * @param {*} index 
     */
    addItem(item, index) {
        if (index === undefined) {
            index = this.items.length;
        }
        item.el = Dom.append(this.root, 'div', item.separator ? 'ctx-separator' : ['ctx-item', item.sub ? 'ctx-sub' : ''],
            item.separator ? null :
                (
                    '<span class="icon">' + (item.icon ? ('<img src="' + item.icon + '">') : '') + '</span>' +
                    '<span>' + item.name + '</span>' +
                    (item.sub ? '<span class="item-more">>></span>' : '')
                ), null, {
                dataIndex: index
            });
    }

    /**
     * 显示
     * @api
     * @param {*} event 
     * @param {*} isHide 是否是隐藏操作
     */
    show(event, isHide, ignorePosition) {
        this.root.style.display = isHide ? 'none' : 'block';
        if (isHide) {
            this.hideSub();
            this.dimmer.show(true);
            return false;
        }

        if (!event) {
            event = this.event;
        }

        this.dimmer.show();

        if (ignorePosition || !event) {
            return false;
        }

        var x = event.clientX,
            y = event.clientY,
            size = Dom.size(this.root),
            bodySize = Dom.size(document.body);

        if (x + size.w > bodySize.w) {
            x = x - size.w;
        }

        if (y + size.h > bodySize.h) {
            y = y - size.h;
        }

        Dom.styles(this.root, {
            left: x + 'px',
            top: y + 'px'
        });
    }

    disabledItem(itemIndexOrCode, disable) {
        let itemIndex = itemIndexOrCode;
        if (typeof itemIndexOrCode === 'string') {
            let i = 0,
                total = this.items.length;
            for (; i < total; i++) {
                if (this.items[i].code === itemIndexOrCode) {
                    itemIndex = i;
                    break;
                }
            }

            // 找不到对应的 code
            if(typeof itemIndex === 'string') {
                return
            }
        }

        let el = this.items[itemIndex].el,
            hasDiabled = el.className.indexOf(' disabled') !== -1;
      
      // undefined 下是切换禁用状态
        if (disable === undefined) {
            disable = !hasDiabled
        }

        if (disable === true) {
            if (!hasDiabled) {
                el.className += ' disabled';
            }
        } else {
            if (hasDiabled) {
                el.className = el.className.replace(' disabled', '');
            }
        }
    }

    showSub(dataIndex) {

        if (this.subRoot && this.subRoot.style.display === 'block') {
            return false;
        }

        if (!this.subRoot) {
            this.subRoot = Dom.append(this.root, 'ul', ['contextmenu', 'contextmenu-sub']);
            Dom.addEvent(this.subRoot, 'click', e => {
                let target = e.target;
                if (target.tagName === 'SPAN') {
                    target = target.parentNode;
                }
                if (target.className.indexOf('ctx-item') !== -1) {
                    if (this.callback(this.subIndex, parseInt(target.getAttribute('data-index')))) {
                        this.show(null, true);
                    }
                }

                return Dom.nodefault(e);
            });
        }

        // 更新内容
        if (this.subIndex !== dataIndex) {
            let liStr = '';
            this.items[dataIndex].sub.forEach((item, i) => {
                liStr += '<li class="' + (item.separator ? 'js-ctx-separator' : 'js-ctx-item') + '" data-index="' + i + '"><span class="icon"></span>' +
                    (item.separator ? '' : ('<span>' + item.name + '</span>')) + '</li>'
            });
            this.subRoot.innerHTML = liStr;
        }

        // 更新位置
        this.subRoot.style.display = 'block';
        let parentSize = Dom.size(this.root);
        this.subRoot.style.left = parentSize.w + 1 + 'px';
        this.subIndex = dataIndex;
    }

    hideSub() {
        if (this.subRoot) {
            this.subRoot.style.display = 'none';
        }
    }


}

export default ContextMenu;